package loja.services;

import java.math.BigDecimal;
import java.util.List;

import loja.dao.DAOFactory;
import loja.dao.compra.pedido.PedidoCompraDAO;
import loja.model.compra.Compra;
import loja.model.compra.ItemCompra;
import loja.model.compra.pedido.ItemPedidoCompra;
import loja.model.compra.pedido.ItemPedidoCompraStatusType;
import loja.model.compra.pedido.PedidoCompra;
import loja.model.estoque.ItemEstoque;
import loja.services.factory.ServiceFactory;

public class PedidoCompraService {

	private PedidoCompraDAO pedidoCompraDAO;
	private ServiceFactory serviceFactory;

	public PedidoCompraService(ServiceFactory serviceFactory,
			DAOFactory daoFactory) {
		this.pedidoCompraDAO = daoFactory.getPedidoCompraDAO();
		this.serviceFactory = serviceFactory;
	}

	public void incluirPedidoCompra(PedidoCompra pedidoCompra) {
		pedidoCompraDAO.incluir(pedidoCompra);

	}

	public List<PedidoCompra> listarPedidosCompra() {
		return pedidoCompraDAO.listar();
	}

	public void removerPedidoCompra(PedidoCompra pedidoCompra) {
		pedidoCompraDAO.remover(pedidoCompra);
	}

	public void alterarPedidoCompra(PedidoCompra pedidoCompra) {
		pedidoCompraDAO.alterar(pedidoCompra);
	}

	public List<ItemPedidoCompra> listarItensPedidoCompraEmAberto() {
		return pedidoCompraDAO.listarItensPedidoCompraAberto();
	}

	public List<ItemPedidoCompra> listarItensPedidoCompraEmAbertoSemPedido() {
		return pedidoCompraDAO.listarItensPedidoCompraAbertoSemPedido();
	}

	public PedidoCompra consultarPorId(Long id) {
		return pedidoCompraDAO.consultarPedidoCompra(id);
	}

	public ItemPedidoCompra consultarItemPedidoCompraPorId(Long id) {
		return pedidoCompraDAO.consultarItemPedidoCompraPorId(id);
	}

	public void alterarItemPedidoCompra(ItemPedidoCompra itemPedidoCompra) {
		pedidoCompraDAO.alterarItemPedidoCompra(itemPedidoCompra);

	}

	public void atualizarStatusItensPedidoCompraEmAberto(Compra compra) {
		for (ItemCompra itemCompra : compra.getItensCompra()) {
			atualizaStatusItemPedidoCompra(itemCompra);
		}
	}

	private void atualizaStatusItemPedidoCompra(ItemCompra itemCompra) {

		Long idItemEstoqueItemCompra = itemCompra.getItemEstoque()
				.getIdItemEstoque();
		Integer quantidadeAtual = itemCompra.getItemEstoque()
				.getQuantidadeEstoque();

		for (ItemPedidoCompra itemPedidoCompra : listarItensPedidoCompraEmAberto()) {
			ItemEstoque itemEstoque = itemPedidoCompra.getItemEstoque();
			Long idItemEstoqueItemPedidoCompra = itemEstoque.getIdItemEstoque();
			Integer quantidadeMinimaItemEstoque = itemEstoque
					.getEstoqueMinimo();
			quantidadeAtual = quantidadeAtual - quantidadeMinimaItemEstoque;

			if (idItemEstoqueItemCompra
					.compareTo(idItemEstoqueItemPedidoCompra) == 0) {
				if (quantidadeAtual >= 0) {
					itemPedidoCompra
							.setStatus(ItemPedidoCompraStatusType.CONCLUIDO);
				} else {
					itemPedidoCompra
							.setStatus(ItemPedidoCompraStatusType.PENDENTE);
				}

			}
		}
	}

	public void geraItensPedidoCompra(List<ItemEstoque> listaItensEstoque) {
		for (ItemEstoque itemEstoque : listaItensEstoque) {
			geraItemPedidoCompra(itemEstoque);
		}

	}

	private void geraItemPedidoCompra(ItemEstoque itemEstoque) {
		if (itemEstoque.isEstoqueEmFalta()) {
			pedidoCompraDAO
					.incluirOuAtualizarItemPedidoCompra(createItemPedidoCompra(itemEstoque));
		}
	}

	private ItemPedidoCompra createItemPedidoCompra(ItemEstoque itemEstoque) {

		ItemPedidoCompra itemPedidoCompra = procurarItemPedidoCompra(itemEstoque);

		if (!verificarQuantidadeProgramada(itemPedidoCompra))
			itemPedidoCompra = setupItemPedidoCompra(itemPedidoCompra);

		return itemPedidoCompra;

	}

	private ItemPedidoCompra procurarItemPedidoCompra(ItemEstoque itemEstoque) {

		Long idItemEstoque = itemEstoque.getIdItemEstoque();

		for (ItemPedidoCompra itemPedidoCompraEmAberto : listarItensPedidoCompraEmAberto()) {
			Long idItemEstoquePedidoCompra = itemPedidoCompraEmAberto
					.getItemEstoque().getIdItemEstoque();
			if (idItemEstoque.compareTo(idItemEstoquePedidoCompra) == 0)
				return itemPedidoCompraEmAberto;
		}

		ItemPedidoCompra itemPedidoCompra = new ItemPedidoCompra();
		itemPedidoCompra.setItemEstoque(itemEstoque);
		itemPedidoCompra.setStatus(ItemPedidoCompraStatusType.ABERTO);

		return itemPedidoCompra;
	}

	private ItemPedidoCompra setupItemPedidoCompra(
			ItemPedidoCompra itemPedidoCompra) {

		ItemEstoque itemEstoque = itemPedidoCompra.getItemEstoque();
		ItemCompra itemCompra = procurarItemCompra(itemPedidoCompra);
		Integer quantidadeVerificada = itemCompra.getQuantidade();
		BigDecimal precoVerificado = itemCompra.getPreco();

		while (quantidadeVerificada < itemEstoque.getEstoqueMinimo()) {
			quantidadeVerificada += itemCompra.getQuantidade();
			precoVerificado = precoVerificado.add(itemCompra.getPreco());
		}

		itemPedidoCompra.setQuantidade(quantidadeVerificada);
		itemPedidoCompra.setPreco(precoVerificado);

		return itemPedidoCompra;
	}

	private boolean verificarQuantidadeProgramada(
			ItemPedidoCompra itemPedidoCompra) {

		ItemEstoque itemEstoque = itemPedidoCompra.getItemEstoque();
		Integer quantidadeItemPedido = itemPedidoCompra.getQuantidade();
		Integer estoqueDisponivel = itemEstoque.getQuantidadeEstoque()
				- itemEstoque.getQuantidadeReservada();
		Integer quantidadeProgramada = estoqueDisponivel + quantidadeItemPedido;
		boolean status = (quantidadeProgramada.compareTo(itemEstoque
				.getEstoqueMinimo()) > 0);

		return status;
	}

	private ItemCompra procurarItemCompra(ItemPedidoCompra itemPedidoCompra) {

		ItemCompra itemCompra = null;
		Long idItemEstoque = itemPedidoCompra.getItemEstoque()
				.getIdItemEstoque();

		for (ItemCompra itemCompraVerificado : this.serviceFactory
				.getCompraService().listarItensCompras()) {
			Long idItemEstoqueItemCompraVerificado = itemCompraVerificado
					.getItemEstoque().getIdItemEstoque();
			if (idItemEstoque.compareTo(idItemEstoqueItemCompraVerificado) == 0)
				itemCompra = itemCompraVerificado;
		}

		if (itemCompra == null)
			itemCompra = new ItemCompra();

		return itemCompra;
	}

}
